package chat

import (
	"api/internal/svc"
	"encoding/json"
	"github.com/gorilla/websocket"
	"github.com/zeromicro/go-zero/core/logx"
	"net/http"
	"strconv"
	"user_srv/user"
)

// UserConn 是全局映射表，用于存储「用户ID字符串」与「对应WebSocket连接」的关联关系
// 目的是后续可通过用户ID快速找到其WebSocket连接，实现定向消息推送
var UserConn = make(map[string]*websocket.Conn)

// SendMessageHandler 是处理「WebSocket消息接收+标记消息已读」的核心Handler
// svcCtx 是服务上下文，用于获取RPC客户端等依赖资源
func SendMessageHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 初始化WebSocket升级器：负责将HTTP连接升级为WebSocket连接
		upgrader := websocket.Upgrader{
			// 跨域检查函数：返回true表示允许所有来源的跨域WebSocket连接（生产环境需按需限制）
			CheckOrigin: func(r *http.Request) bool {
				return true // 开发阶段临时允许所有跨域，生产需替换为严格校验逻辑
			},
		}

		// 从请求Form中提取用户ID
		userIdStr := r.Form.Get("userId")
		if userIdStr == "" {
			logx.Error("用户ID不存在于Form中，请检查中间件配置")
			http.Error(w, "认证失败：用户信息缺失", http.StatusUnauthorized)
			return
		}

		// 将用户ID从字符串转换为整数（后续逻辑需int类型）
		userId, err := strconv.Atoi(userIdStr)
		if err != nil {
			logx.Error("用户ID格式错误：", err)
			http.Error(w, "认证失败：用户信息格式错误", http.StatusInternalServerError)
			return
		}

		// 执行HTTP -> WebSocket连接升级
		conn, err := upgrader.Upgrade(w, r, nil) // 升级HTTP连接为WebSocket连接
		if err != nil {
			logx.Error("WebSocket升级失败:", err) // 记录错误日志
			return                            // 升级失败直接返回，不继续后续逻辑
		}
		defer conn.Close() // 函数结束时自动关闭连接，避免资源泄漏

		// 将当前WebSocket连接存入全局映射表，键为用户ID字符串（方便后续通过ID查找连接）
		UserConn[strconv.Itoa(userId)] = conn

		// 持续监听WebSocket消息（长连接核心逻辑）
		for {
			// 读取WebSocket消息：返回「消息类型（忽略）、消息内容p、错误err」
			_, p, err := conn.ReadMessage()
			if err != nil {
				logx.Error("读取消息失败:", err)
				break // 读取失败（如客户端断开）则退出循环
			}

			// 定义接收消息的结构体（对应客户端发送的JSON格式）
			var Message UserProduce // 声明消息结构体变量
			// 解析JSON消息到结构体
			if err := json.Unmarshal(p, &Message); err != nil {
				logx.Error("JSON解析失败:", err)
				conn.WriteMessage(websocket.TextMessage, []byte("消息格式错误"))
				continue // 解析失败，继续下一次消息读取
			}

			// 调用RPC服务「标记消息为已读」
			_, err = svcCtx.UserRpc.MarkMessageRead(r.Context(), // 透传请求上下文（用于超时、链路追踪等）
				&user.MarkMessageReadReq{ // 构造RPC请求参数
					MessageId: int64(Message.Id), // 传入要标记的消息ID
				})

			if err != nil {
				logx.Error("RPC调用失败:", err)
				conn.WriteMessage(websocket.TextMessage, []byte("服务错误"))
				continue
			}

			conn.WriteMessage(websocket.TextMessage, []byte("阅读成功"))
		}
	}
}

// UserProduce 定义用户消息结构
type UserProduce struct {
	Id int `json:"id"` // 消息ID
}
